package com.rock.code.provider.es.controller;

import com.rock.code.base.controller.BaseController;
import com.rock.code.common.comm.DesEncrypterIsmp;
import com.rock.code.common.comm.RandomGUID;
import com.rock.code.system.user.domain.TbSysLoginmsg;
import com.rock.code.system.user.service.TbSysLoginmsgService;
import net.sf.json.JSONObject;
import org.apache.http.HttpHost;
import org.elasticsearch.action.DocWriteResponse;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.support.replication.ReplicationResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.query.RangeQueryBuilder;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.sort.FieldSortBuilder;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * es接口
 */
@Controller
@RequestMapping("/elasticsearch")
public class ElasticSearchInterfaceController extends BaseController {

    @Resource
    private TbSysLoginmsgService tbSysLoginmsgService;

    //常量
    private static String hostname = "192.168.159.143"; // 服务器地址
    private static int port = 9200; // http端口
    private static String scheme = "http";

    //高级别的Rest客户端
    private RestHighLevelClient client;

    //初始化客户端
    public void getClient() {
        try {
            client = new RestHighLevelClient(
                    RestClient.builder(
                            new HttpHost(hostname, port, scheme)));
            System.out.println("已获取client……");
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println("client获取失败!");
            closeClient();
        }

    }

    //关闭客户端
    public void closeClient() {
        if (client != null) {
            try {
                client.close();
                System.out.println("已关闭client……");
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }


    /**
     * 创建es索引，新增数据
     *
     * @param index es索引名称
     * @param list  数据集
     * @throws IOException
     */
    public void addKpis(String index, List list) throws IOException {
        //开客户端
        //三、作为对象键对提供的文档源，它被转换为JSON格式
        IndexRequest indexRequest = new IndexRequest(index);
        SimpleDateFormat sbf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//时间格式转换
        for (int i = 0; i < list.size(); i++) {
            String record = (String) list.get(i);
            System.out.println("字符串为：" + record);
            String[] recordStr = record.split("");
            System.out.println("字符串数组为：" + recordStr);
            indexRequest.id(RandomGUID.getRandomGUID()) //GUID。若id重复，数据会被覆盖
                    .source("unit_id", "10-10-24-13:192_168_56_19-ifOutOctets",
                            "kpi_id", "PM-00-01-002-10",
                            "kpi_value", "1000Kbps",
                            "postion", "n/r",
                            "startTime", sbf.format(new Date()),
                            "endTime", sbf.format(new Date())
                    );
        }

        //同步执行，必须等待执行结果后，才能继续走下面的代码。也有异步执行的方式
        //当以下列方式执行索引请求时，客户端在继续执行代码之前等待返回索引响应
        IndexResponse indexResponse = client.index(indexRequest, RequestOptions.DEFAULT);
        System.out.println(indexResponse);

       /* String index = indexResponse.getIndex();
        String id = indexResponse.getId();*/

        if (indexResponse.getResult() == DocWriteResponse.Result.CREATED) {
            //处理(如果需要)第一次创建文档的情况

        } else if (indexResponse.getResult() == DocWriteResponse.Result.UPDATED) {
            //处理(如果需要)将文档重写为已经存在的情况

        }
        ReplicationResponse.ShardInfo shardInfo = indexResponse.getShardInfo();
        if (shardInfo.getTotal() != shardInfo.getSuccessful()) {
            //处理成功碎片的数量少于总碎片的情况

        }
        if (shardInfo.getFailed() > 0) {
            for (ReplicationResponse.ShardInfo.Failure failure :
                    shardInfo.getFailures()) {
                String reason = failure.reason();
                //处理潜在的故障
            }
        }
    }


    /**
     * 根据条件查询es数据
     *
     * @param ip        unit_id的IP
     * @param kbp       unit_id的KBP
     * @param kpi_id    kpi_id
     * @param startTime 起始时间
     * @param startTime 结束时间
     * @param startRow  开始行数
     * @param endRow    结束行数
     */
    @ResponseBody
    @RequestMapping(value = "/kpisByParams", method = RequestMethod.POST)
    public Object kpisByParams(String index, String ip, String kbp, String kpi_id, String startTime,
                               String endTime, String startRow, String endRow) throws Exception {

        if (visit(request).equals("0000")) {
            JSONObject json = json = new JSONObject();
            json.put("error", "unauthorized");
            json.put("error_description", "Full unauthorized is required  to assess this resource");
            ajaxJson.setSuccess(false);
            ajaxJson.setMsg("验证失败");
            ajaxJson.setResult(json);
            return ajaxJson;
        }

        getClient();

        //创建SeachRequest 如果没有参数，则运行所有索引
        SearchRequest searchRequest = new SearchRequest("kpis");

        //时间范围的设定
        RangeQueryBuilder rangequerybuilder = QueryBuilders
                .rangeQuery("data_time")
                .from(startTime).to(endTime);

        //多参数，用must()
        QueryBuilder queryBuilder = QueryBuilders.boolQuery()
                .must(QueryBuilders.matchPhraseQuery("unit_id", kbp))
                .must(QueryBuilders.matchPhraseQuery("unit_id", ip))
                .must(QueryBuilders.matchPhraseQuery("kpi_id", kpi_id))
                .must(rangequerybuilder);

        //大多数搜索参数都添加到SearchSourceBuilder中。它为进入搜索请求体的所有内容提供setter。
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();

        //排序、分页
        searchSourceBuilder.sort(new FieldSortBuilder("_id").order(SortOrder.ASC)).from(Integer.parseInt(startRow)).size(Integer.parseInt(endRow));

        //生成DSL查询语句
        searchSourceBuilder.query(queryBuilder);

        //将SearchSourceBuilder添加到SeachRequest
        searchRequest.source(searchSourceBuilder);
        SearchResponse search = client.search(searchRequest, RequestOptions.DEFAULT);
        SearchHits hits = search.getHits();

        //处理数据
        List<Map> list = new ArrayList();
        Map<String, Object> maps = new HashMap();
        LinkedHashMap<String, List> resultMap = new LinkedHashMap();
        for (SearchHit hit : hits) {
            maps = hit.getSourceAsMap();
            list.add(maps);
        }
        for (int i = 0; i < list.size(); i++) {
            //System.out.println(list.get(i));
            Map map = list.get(i);
            //根据key获取时间："10-10-24-12:192_168_56_18-memory",
            String unit_id = map.get("unit_id").toString();
            //以空格拆分时间，取第0位：10-10-24-12
            String key = unit_id.split(":")[0];
            //若new的Map中不存在某个key，则将该key对应的value存入list中并将此list存放进new的 Map中，key不变
            if (!resultMap.containsKey(key)) {
                List newList = new ArrayList();
                newList.add(map);
                resultMap.put(key, newList);
            } else {//若存在,则直接将其value值add进该key对应的list中
                List resultList = resultMap.get(key);
                resultList.add(map);
                resultMap.put(key, resultList);
            }
        }

        closeClient();
        return resultMap;

    }


    /* **
      * @return net.sf.json.JSONObject
      * @Author zhangli
      * @Description //TODO 授权验证：是否有权限获取API信息
      * @Date 15:58 2019/4/15
      * @Param [request]
      **/
    public String visit(HttpServletRequest request) {
        if (request == null) {
            return "0000";
        }
        Map<String, String> params = new HashMap<String, String>();
        Enumeration headerNames = request.getHeaderNames();
        while (headerNames.hasMoreElements()) {
            String key = (String) headerNames.nextElement();
            String value = request.getHeader(key);
            params.put(key, value);
        }

        String userId = params.get("userid");
        String passwd = params.get("passwd");
        Map<String, Object> _map = new HashMap<>();
        _map.put("loginCode", userId);
        _map.put("loginPasswd", DesEncrypterIsmp.encrypt(passwd));
        TbSysLoginmsg loginmsg = null;
        try {
            loginmsg = tbSysLoginmsgService.loginByParaMap(_map);
        } catch (Exception e) {
            e.printStackTrace();
        }
        if (loginmsg != null) {
            return "1111";
        } else {
            return "0000";
        }
    }
}
